<template>
    <div class="ph-slider" ref="slider" @click="click">
        <div v-if="!transparent" :class="['ph-slider-p-indicator',theme]" :style="style.width"></div>
        <button :class="['ph-slider-indicator',showTip?'ph-tooltip-self':'']" :data-title="tip" :style="style.transform" @mousedown.stop="mousedown"></button>
    </div>
</template>
<script lang="ts">
import { computed, defineComponent , onBeforeUpdate, onMounted, ref } from 'vue'

export default defineComponent({
    props:{
        type:{type:String},
        format:{type:String,default:"v"},
        showTip:{type:Boolean,default:true},
        transparent:{
            type:Boolean,
            default:false
        },
        value:{
            type:Number,
            default:0
        },
        max:{
            type:Number,
            default:0
        }
    },
    setup(props,{emit}){
        const ox = ref(0)
        const width = ref(0)
        const slider = ref<HTMLElement|null>(null)
        const theme = computed(()=>{
            return props.type?"ph-slider-"+props.type:""
        })
        const tip = computed(()=>{
            return props.format.replace(/v/g,(a:string,b:string)=>{
                return Math.round(props.value)+""
            })
        })
        const tx = computed(()=>{
            const ex = ox.value+props.value*width.value/props.max
            let tx = ex - ox.value;
                tx = Math.max(tx,0)
                tx = Math.min(width.value,tx)
            return tx
        })
        const notify = (ex:number)=>{
            const value = (ex-ox.value)*props.max/width.value
            if(value<0||value>props.max)return
            emit("change",value)
        }
        const style = computed(()=>{
            return {
                transform:{
                    transform: `translateX(${tx.value}px)`
                },
                width:{
                    width:`${tx.value}px`
                }
            }
        })
        
        const mousemove = (e:MouseEvent)=>{
            notify(e.pageX)
        }
        const mouseup = ()=>{
            document.removeEventListener("mousemove",mousemove)
            document.removeEventListener("mouseup",mouseup)
        }
        const mousedown = ()=>{
            updateSiderUi()
            document.addEventListener("mousemove",mousemove)
            document.addEventListener("mouseup",mouseup)
        }
        const click = (e:MouseEvent)=>{
            updateSiderUi()
            notify(e.pageX)
        }
        const updateSiderUi = ()=>{
            const rect = slider?.value?.getBoundingClientRect()
            if(!rect)return
            if(width.value != rect.width)
                width.value = rect.width
            if(ox.value != rect.left)
                ox.value = rect.left
        }
        onMounted(()=>{
            updateSiderUi()
        })
        onBeforeUpdate(()=>{
            setTimeout(()=>{
                updateSiderUi()
            })
        })
        return {style,theme,mousedown,click,slider,tip}
    }
})
</script>
<style lang="scss" scoped>
.ph-slider{
    user-select: none;
    position: relative;
    height: 10px;
    overflow: visible;
    border-radius: 10px;
    background-color: var(--ph-light-d1);
    cursor: pointer;
    &-p-indicator{
        border-radius: 10px;
        background-color: var(--ph-c);
        height: 10px;
        width: 100px;
    }
    &-success{
        background-color: var(--ph-success);
    }
    &-primary{
        background-color: var(--ph-primary);
    }
    &-info{
        background-color: var(--ph-info);
    }
    &-danger{
        background-color: var(--ph-danger);
    }
    &-warning{
        background-color: var(--ph-warning);
    }
    
    &-indicator{
        --ph-slider-id-dim:14px;
        touch-action: manipulation;
        cursor: pointer;
        background-image: none;
        white-space: nowrap;
        user-select: none;
        width: var(--ph-slider-id-dim);
        height: var(--ph-slider-id-dim);
        background-color: var(--ph-light-l1);
        border-radius: 50%;
        border:none;
        box-shadow: 0 1px 0.0585rem 1px #666;
        position: absolute;
        top: 0;
        bottom: 0;
        margin: auto;
        left: -7px;
        z-index: 2;
    }
}
</style>
